package com.osdp.sc.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Maps;
import com.osdp.common.constant.CommonConstant;
import com.osdp.common.exception.PlatformException;
import com.osdp.common.util.ConvertUtil;
import com.osdp.sc.dto.PermissionDTO;
import com.osdp.sc.entity.ScPermission;
import com.osdp.sc.mapper.ScPermissionMapper;
import com.osdp.sc.service.IScPermissionService;
import com.osdp.sc.service.IScRolePermissionService;
import com.osdp.sc.uitl.Fields;
import com.osdp.sc.vo.ScPermissionVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.CollectionUtils;
import org.springframework.util.PathMatcher;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
//@Transactional
public class ScPermissionServiceImpl extends ServiceImpl<ScPermissionMapper, ScPermission> implements IScPermissionService {
//    @Value("${tenant.base.tenantId}")
//    private String baseTenantId;

    @Resource
    private ScPermissionMapper scPermissionMapper;

    @Resource
    private IScRolePermissionService scRolePermissionService;

    /**
     * 根据父节点查询子节点数据
     * @param parentId 父ID 根节点为:"-1"
     * @param parentName 父节点名称
     * @return List<ScPermissionVo>
     */
    @Override
    public List<ScPermissionVo> queryListByParentId(String parentId, String parentName) {
        QueryWrapper<ScPermission> query = new QueryWrapper<ScPermission>();
//        if(parentId == null || parentId == ""){
//            query.eq(Fields.ScPermissionQ.parentId, parentId)
//                .or().isNull(Fields.ScPermissionQ.parentId);
//        }else {
            query.eq(Fields.ScPermissionQ.parentId, parentId);
//        }
        query.orderByAsc(Fields.ScPermissionQ.sortNo);
        List<ScPermission> list = super.list(query);
        List<ScPermissionVo> resultList = new ArrayList<>();
        if(!CollectionUtils.isEmpty(list)) {
            if(parentId.equals(CommonConstant.TREE_ROOT_VALUE)){
                resultList = ConvertUtil.sourceToTarget(list, ScPermissionVo.class);
            } else {
                for(ScPermission entity : list){
                    ScPermissionVo vo =  ConvertUtil.sourceToTarget(entity, ScPermissionVo.class);
                    vo.setParentId(parentId);
                    vo.setParentName(parentName);
                    resultList.add(vo);
                }
            }
        }
        return resultList;
    }

    /**
     *
     *
     * @param permissionVo
     * @return
     */

    //@CacheEvict 是用来标注在需要清除缓存元素的方法或类上的。当标记在一个类上时表示其中所有的方法的执行都会触发缓存的清除操作。
    //    @CacheEvict(value = "permission", allEntries = true)
    @Transactional
    @Override
    public ScPermissionVo insertScPermission(ScPermissionVo permissionVo) {
        ScPermission entity = ConvertUtil.sourceToTarget(permissionVo, ScPermission.class);
        if(!StringUtils.equals(entity.getParentId(),CommonConstant.TREE_ROOT_VALUE)) {
              this.update(new UpdateWrapper<ScPermission>()
                    .set(Fields.ScPermissionQ.isLeaf, CommonConstant.FLAG_ONE_1)// 更新上级为不是叶子节点
                    .eq(Fields.ScPermissionQ.id, entity.getParentId()));
        }
        entity.setLeaf(false); //是叶子节点
        this.save(entity);
        permissionVo = ConvertUtil.sourceToTarget(entity, ScPermissionVo.class);
        return permissionVo;
    }

    @Transactional
    @Override
    public ScPermissionVo updateScPermission(ScPermissionVo permissionVo) {
        ScPermission entity = ConvertUtil.sourceToTarget(permissionVo, ScPermission.class);
        ScPermission scPermission = this.getById(entity.getId());
        if(scPermission == null){
            throw new PlatformException("修改的菜单信息不存在！");
        }
        this.updateById(entity);
        permissionVo = ConvertUtil.sourceToTarget(entity, ScPermissionVo.class);
        return permissionVo;
    }

    @Override
    @Transactional
    public boolean deleteScPermission(String id) {
        ScPermission entity = super.getById(id);
        if(entity == null){
            throw new PlatformException("对象不存在！");
        }
        String parentId = entity.getParentId();
        long count = super.count(new QueryWrapper<ScPermission>().eq(Fields.ScPermissionQ.parentId, parentId));
        if(count == 1){
//            this.scPermissionMapper.updateMenuLeaf(parentId, CommonConstant.FLAG_ONE_1);
            ScPermission parentEntity = this.getById(parentId);
            boolean flag = this.update(parentEntity,new UpdateWrapper<ScPermission>()
                    .set(Fields.ScPermissionQ.isLeaf,CommonConstant.FLAG_ONE_1)
                    .eq(Fields.ScPermissionQ.id, parentId));
            if(flag == false){
                throw new PlatformException("更新父节点失败！");
            }
        }
        boolean bool = this.removeChildrenBy(entity.getId());
        return super.removeById(id) && bool;
    }

    /**
     * 根据父id删除其关联的子节点数据
     * @param parentId
     */
    public boolean removeChildrenBy(String parentId) {
        QueryWrapper<ScPermission> query = new QueryWrapper<ScPermission>();
        query.eq(Fields.ScPermissionQ.parentId, parentId);
        // 查出该主键下的所有子级
        List<ScPermission> permissions = this.list(query);
        boolean flag = true;
        if(!CollectionUtils.isEmpty(permissions)  && permissions.size()>0){
            // 再遍历刚才查出的集合, 根据每个对象,查找其是否仍有子级
            permissions.stream().forEach(e ->{
                String id = e.getId();
                long childCount = super.count(new QueryWrapper<ScPermission>()
                        .eq(Fields.ScPermissionQ.parentId, id));
                // 如果有, 则递归
                if(childCount > 0){
                    this.removeChildrenBy(id);
                }
            });
            // 如果查出的集合不为空, 则删除所有子节点。
            flag = super.remove(query);
        }
        return flag;
    }

    /**
     * 构建资源树
     * @param permissionList
     * @return
     */
    @Override
    public Set<ScPermissionVo> createPermissionTree(List<ScPermission> permissionList){
        Map<String, ScPermissionVo> permMap = Maps.newHashMap();
        Set<ScPermissionVo> rootPermSet = new TreeSet<ScPermissionVo>();
        if (permissionList != null) {
            for (ScPermission scPermission : permissionList) {
                ScPermissionVo vo = ConvertUtil.sourceToTarget(scPermission,ScPermissionVo.class);
                permMap.put(scPermission.getId(), vo);
            }
        }
        Set<String> keys = permMap.keySet();
        for (String key : keys) {
            ScPermissionVo vo = permMap.get(key);
            if (StringUtils.equals(vo.getParentId(),CommonConstant.TREE_ROOT_VALUE)) { // 父节点
                rootPermSet.add(vo);
            } else {
                ScPermissionVo parent = permMap.get(vo.getParentId());
                if (parent != null) {
                    parent.getChildren().add(vo);
                }
            }
        }
        return rootPermSet;
    }

    @Override
    public List<ScPermission> queryAllPermissionList() {
        return this.list(new QueryWrapper<ScPermission>()
                .orderByAsc(Fields.ScPermissionQ.sortNo));
//        return ConvertUtil.sourceToTarget(permissions, PermissionVo.class);

    }

    @Override
    public List<ScPermissionVo> queryPermissionsByRoleId(String roleId){

        return null;
    }

    //------------------------------登录信息查询---------------------------------//

    /**
     * 根据用户ID 查询所拥的菜单权限
     * @param userId String
     * @return List<ScPermission>
     */
    @Override
    public List<PermissionDTO> queryPermissionsByUserId(String userId) {
        List<ScPermission> permissions = this.scPermissionMapper.queryPermissionByUserId(userId,null);
        return ConvertUtil.sourceToTarget(permissions, PermissionDTO.class);
    }

    @Override
    public Optional<List<PermissionDTO>> queryPermsButtonAndAPIByRoleCode(Set<String> roleCodes, String tenantId) {
        List<ScPermission> permissions = scPermissionMapper.queryPermissionByRoleCodes(roleCodes, tenantId);
        return Optional.ofNullable(ConvertUtil.sourceToTarget(permissions, PermissionDTO.class));
    }

    @Override
    public List<PermissionDTO> queryPermissionButtonByUserId(String userId){
        List<ScPermission> permissions = this.scPermissionMapper.queryPermissionByUserId(userId,CommonConstant.FLAG_TWO_2);
        return ConvertUtil.sourceToTarget(permissions, PermissionDTO.class);
    }

    @Override
    public List<PermissionDTO> queryPermissionAPIByUserId(String userId){
        List<ScPermission> permissions = this.scPermissionMapper.queryPermissionByUserId(userId,CommonConstant.FLAG_THREE_3);
        return ConvertUtil.sourceToTarget(permissions, PermissionDTO.class);
    }

    @Override
    public List<String> queryPermsCodeByUserId(String userId) {
        List<ScPermission> permissions = this.scPermissionMapper.queryPermissionByUserId(userId,null);
        List<String> permsCodes = new LinkedList<>();
        permissions.stream().map(ScPermission::getPermsCode).filter(e->StringUtils.isNotEmpty(e)).collect(Collectors.toList());
        return null;
    }

    /**
     * 对URL进行权限检查
     * @param uri 如：/api/auth/homePage/getUserInfo
     * @param method GET,POST,PUT,DELETE,...
     * @param authoritys 角色编号
     * @return
     */
    @Override
    public boolean allow(String uri, String method, Set<String> authoritys) {
        PathMatcher matcher = new AntPathMatcher();
        //处理角色列表
        if(authoritys==null||authoritys.isEmpty()) {
            return false;
        }
        Set<String> roles = new HashSet<>();
        for (String role : authoritys) {
            if(role.startsWith(CommonConstant.PREFIX_ROLE_CODE)) {
                roles.add(role.substring(5, role.length()));
            }
        }
        String tenantId = null; // TokenUtil.getTenantId(TokenHolder.getToken());
        //通过角色列表查询出来权限列表，主要是url和请求方法（状态为1的权限列表，也就是生效的配置，如果配置不生效，也相当于没有权限，白名单模式）
        Optional<List<PermissionDTO>> permissionOpt = queryPermsButtonAndAPIByRoleCode(roles,tenantId);
        if(!permissionOpt.isPresent() || permissionOpt.get().isEmpty()){
            if(log.isErrorEnabled()){
                log.error(String.format("uri:%s mehtod:%s 对应的权限不存在",uri,method  ));
            }
            return false;
        }
        List<PermissionDTO> permissions = permissionOpt.get();
        //权限过滤，相当于是白名单
        for (PermissionDTO permission : permissions) {
            if(permission!=null && StringUtils.isNotBlank(permission.getUrl())) {
                //如果路径匹配上，再判断需不需要检验请求方法
                if(matcher.match(permission.getUrl(), uri)) {
                    if(permission.checked()) {
                        if(StringUtils.equalsIgnoreCase(method, permission.getRequestType())) {
                            return true;
                        }else {
                            return false;
                        }
                    }else{
                        return true;
                    }
                }
            }
        }
        return false;
    }
    /**
     * 权限拷贝
     * @param tenantId
     * @param roleId
     */
//    @Override
//    public void permissionCopy(String tenantId, String roleId) {
//        Map<String,Object> paramMap = Maps.newHashMap();
//        paramMap.put("tenant_id",baseTenantId);
//        List<ScPermission> sourecePermList = this.listByMap(paramMap);
//        List<ScPermission> targerPermList = Lists.newArrayList();
//        String prefix = HelperUtil.randomGen(8);//这里采取比较暴力简单的方法，截取原ID前8位，统一修改。
//        sourecePermList.stream().forEach(sourcePermission ->{
//            ScPermission targerPerm = new ScPermission();
//            BeanUtils.copyProperties(sourcePermission,targerPerm);
//            targerPerm.setTenantId(tenantId);
//            targerPerm.setCreateTime(new Date());
//            targerPerm.setUpdateTime(new Date());
//            targerPerm.setId(prefix + sourcePermission.getId().substring(7, sourcePermission.getId().length()));
//            if(StringUtils.isNotEmpty(targerPerm.getParentId())){
//                targerPerm.setParentId(prefix + sourcePermission.getParentId().substring(7, sourcePermission.getParentId().length()));
//            }
//            targerPermList.add(targerPerm);
//        });
//        this.saveBatch(targerPermList);
//        //更新租户ID
//        List<ScRolePermission> rolePermissionList =  targerPermList.stream().map(permission-> new ScRolePermission(roleId,permission.getId()))
//                .collect(Collectors.toList());
//        scRolePermissionService.saveBatch(rolePermissionList);//与角色关联
//    }
}
